/*
 * @Author: song
 * @Description: 技能编辑器 刻度盘
 * @Date: 2024年04月28日 星期日 16:04:25
 * @Modify:
 */

using System.Collections.Generic;
using SCore.Editor.WindowDraw;
using UnityEditor;
using UnityEngine;

namespace Function.SkillEditor.Editor
{
    public class SkillTimeLineMarkerView : NCommonView
    {
        private static int MIN_FRAME = 3; //最少显示多少Frame
        public static int DEFALUTFRAME = 100; //默认显示多少刻度
        public static float MIN_SCALE = (float)MIN_FRAME / DEFALUTFRAME; //最小的缩放值
        private static float DEFAULT_SCALE = 1; //默认缩放值

        [Tooltip("刻度盘的缩放值")] public float _marKerScale = DEFAULT_SCALE;
        [Tooltip("当前刻度盘已经滑动的位置")] public float _startFrame = 0.0f;

        private ELineView _eLineView;


        private static Dictionary<int, int> _markerMap = new Dictionary<int, int>()
        {
            { 1, 1 },
            { 20, 5 },
            { 100, 25 },
            { 500, 125 },
            { 2500, 625 },
            { 12500, 3125 },
            { 62500, 15625 },
        };

        public override void OnEnable()
        {
            SkillEditorWindow.EventManager.AddListener<SkillConfigItemData>(SkillEditorEventType.TimeLineEditChange,
                OnTimeLineEditChange);
        }

        public override void OnDisable()
        {
            SkillEditorWindow.EventManager.RemoveListener<SkillConfigItemData>(SkillEditorEventType.TimeLineEditChange,
                OnTimeLineEditChange);
        }

        public void OnMarkerGUI()
        {
            EditorClip.Push(new Rect(_rect.x, _rect.y, _rect.width - 5, _rect.height));
            var parent = GetSubEditorWindow<SkillTimeLineSubWindow>();
            //当前区域应该显示多少帧
            var (showFrame, startFrame, endFrame) = GetStartAndEndFrame();
            //当前的刻度线占的单位大小
            int unitScale = GetNumUnitFrame(Mathf.CeilToInt(showFrame));
            //左边刻度区域
            float leftShow = unitScale - startFrame % unitScale;
            if (startFrame == 0)
            {
                leftShow = 0;
            }

            //一帧显示的区域大小
            float itemWidth = GetUnitWidth(showFrame);
            //实时绘制到的宽度
            float curWidth = GetZeroFrameWidth();
            Stack<float> leftStack = new Stack<float>();
            if (leftShow > 0)
            {
                // 绘制左边间部分
                int drawDepth = 2;
                for (int scale = unitScale; scale >= 1; scale /= 5)
                {
                    drawDepth--;
                    var subline = Mathf.FloorToInt(leftShow / scale);
                    leftShow %= scale;
                    var leftWidth = subline * scale * itemWidth;
                    curWidth += leftWidth;
                    if (drawDepth == 0 && leftWidth != 0)
                    {
                        for (int index = 1; index <= subline; index++)
                        {
                            leftStack.Push(scale * itemWidth * index);
                        }
                    }

                    if (scale == 1 && leftShow > 0)
                    {
                        curWidth += leftShow * itemWidth;
                        break;
                    }
                }
            }

            while (leftStack.Count > 0)
            {
                //绘制
                var lineRect = new Rect(curWidth - leftStack.Pop(), 12, 0.8f, 6.5f);
                EditorGUI.DrawRect(lineRect, EditorDrawHelp._ivory6);
            }

            // 绘制中间部分 头和尾的数字需要绘制上
            int centerShow = Mathf.CeilToInt(startFrame / unitScale) * unitScale;
            int centerEnd = Mathf.FloorToInt(endFrame / unitScale) * unitScale;
            for (int index = centerShow; index <= centerEnd; index += unitScale)
            {
                var lineRect = new Rect(curWidth, 5, 0.8f, 13);
                EditorGUI.DrawRect(lineRect, EditorDrawHelp._ivory6);
                var subUnitScale = unitScale / 5;
                if (subUnitScale >= 1)
                {
                    for (int subOffest = subUnitScale; subOffest < unitScale; subOffest += subUnitScale)
                    {
                        float subX = curWidth + itemWidth * subOffest;
                        var subLineRect = new Rect(subX, 12, 0.8f, 6.5f);
                        EditorGUI.DrawRect(subLineRect, EditorDrawHelp._ivory6);
                    }
                }

                var numRect = new Rect(curWidth, 0, 100, 10);
                EditorGUI.LabelField(numRect, index.ToString());
                curWidth += itemWidth * unitScale;
            }

            EditorClip.Pop();
        }


        //Event
        private void OnTimeLineEditChange(SkillConfigItemData itemData)
        {
            if (itemData != null)
            {
                _marKerScale = itemData.GetEndFrame() / (float)DEFALUTFRAME;
                _marKerScale = Mathf.Max(MIN_SCALE, _marKerScale);
            }
        }

        /// <summary>
        /// 得到当前刻度表绘制数字的帧间隔
        /// </summary>
        /// <param name="showFrame"></param>
        /// <returns></returns>
        private int GetNumUnitFrame(int showFrame)
        {
            int nearestKey = 1;
            foreach (var key in _markerMap.Keys)
            {
                if (key <= showFrame && key > nearestKey)
                {
                    nearestKey = key;
                }
            }

            return _markerMap[nearestKey];
        }

        /// <summary>
        /// 得到一帧绘制的宽度
        /// </summary>
        /// <param name="showFrame"></param>
        /// <returns></returns>
        private float GetUnitWidth(float showFrame)
        {
            return _rect.width / showFrame;
        }


        public void Bind(ELineView eLineView)
        {
            _eLineView = eLineView;
        }


        //得到显示帧数 开始和结束帧
        public (float, float, float) GetStartAndEndFrame()
        {
            float showFrame = _marKerScale * DEFALUTFRAME;
            showFrame = Mathf.Max(showFrame, MIN_FRAME);

            return (showFrame, _startFrame, _startFrame + showFrame);
        }

        //通过帧得到长度
        public float GetXByFrame(int frame)
        {
            var (showFrame, startFrame, endFrame) = GetStartAndEndFrame();
            float itemWidth = GetUnitWidth(showFrame);
            if (frame <= startFrame)
            {
                return -1 * (startFrame - frame) * itemWidth + GetZeroFrameWidth();
            }

            if (frame >= endFrame)
            {
                return _rect.width + GetZeroFrameWidth();
            }

            return (frame - startFrame) * itemWidth + GetZeroFrameWidth();
        }

        //通过长度得到帧
        public int GetIntFrameByX(float x)
        {
            if (x <= GetZeroFrameWidth())
            {
                return 0;
            }

            x -= GetZeroFrameWidth();
            var (showFrame, startFrame, endFrame) = GetStartAndEndFrame();
            float itemWidth = GetUnitWidth(showFrame);
            return Mathf.Max(0, Mathf.RoundToInt(x / itemWidth + startFrame));
        }

        //得到长度占的帧数
        public float GetFrameByLength(float length)
        {
            var (showFrame, startFrame, endFrame) = GetStartAndEndFrame();
            float itemWidth = GetUnitWidth(showFrame);
            return length / itemWidth;
        }


        /// <summary>
        /// 得到第0帧的在刻度盘里的Width
        /// </summary>
        /// <returns></returns>
        public float GetZeroFrameWidth()
        {
            return 10;
        }

        //Event
        public Vector2 _drayStartPos;

        protected override bool MouseWheel(Event evt)
        {
            var (showFrame, startFrame, endFrame) = GetStartAndEndFrame();
            //计算缩放点比例
            var mouse = Event.current.mousePosition.x - _rect.x - GetZeroFrameWidth();
            var center = mouse / (_rect.width - GetZeroFrameWidth());
            center = Mathf.Clamp01(center);
            var direction = Event.current.delta.y;
            direction = direction > 0 ? -0.1f : 0.1f;
            if (direction > 0)
            {
                if (showFrame <= MIN_FRAME)
                {
                    return true;
                }
            }

            startFrame += showFrame * direction * center;
            if (startFrame <= 0)
            {
                startFrame = 0;
                endFrame -= showFrame * direction;
            }
            else
            {
                endFrame -= showFrame * direction * (1 - center);
            }

            endFrame = Mathf.Max(MIN_FRAME, endFrame);
            _startFrame = startFrame;
            _marKerScale = (endFrame - startFrame) / DEFALUTFRAME;
            _marKerScale = Mathf.Max(MIN_SCALE, _marKerScale);
            SkillEditorWindow.EventManager.BroadCast(SkillEditorEventType.TimeLineMarkerChange);
            return true;
        }

        protected override bool MouseDown(Event evt)
        {
            if (evt.button == 2)
            {
                _drayStartPos = evt.mousePosition;
                return true;
            }

            return false;
        }

        protected override bool MouseDrag(Event evt)
        {
            if (evt.button == 2)
            {
                var moveDistance = (evt.mousePosition - _drayStartPos).x;
                var frame = GetFrameByLength(moveDistance);
                _startFrame = Mathf.Max(0,
                    _startFrame - frame);
                _drayStartPos = evt.mousePosition;
                SkillEditorWindow.EventManager.BroadCast(SkillEditorEventType.TimeLineMarkerChange);
                return true;
            }

            return false;
        }
    }
}